package com.streaminggbs.service;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.streaminggbs.common.base.BaseQueryBean;
import com.streaminggbs.common.base.ErrorCodeException;
import com.streaminggbs.entity.*;
import com.streaminggbs.interfaces.*;

import com.streaminggbs.common.utils.IDManager;
import com.streaminggbs.common.utils.RedisUtil;
import com.streaminggbs.common.utils.StringUtil;
import com.streaminggbs.common.utils.Validator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
@Slf4j
public class GbInfoServiceImpl implements GbInfoService {

    @Autowired
    private SettingsDeviceTypeService settingsDeviceTypeService;
    @Autowired
    private SysAuthDeptService sysAuthDeptService;
    @Autowired
    private DeviceInfoService deviceInfoService;
    @Autowired
    private DeviceChannelInfoService deviceChannelInfoService;

    @Override
    public List<GbImport> validGbImport(List<GbImport> list) {
        if(list == null || list.isEmpty()){
            throw new ErrorCodeException(-1, "导入记录为空");
        }

        //验证导入的数据中，gbId是否重复
        Set<String> gbIdSet = new HashSet<>();
        for(GbImport info : list){
            gbIdSet.add(info.getGbId());
            //遍历的同时给ID赋值
            info.setId(IDManager.nextId());
        }
        if(gbIdSet.size() < list.size()){
            throw new ErrorCodeException(-1, "gbId存在重复");
        }
        //将国标编码和生成的ID存入Map，方便取值
        Map<String, String> gbIdMap = new HashMap<>(64);
        for(GbImport info : list){
            gbIdMap.put(info.getGbId(), info.getId());
        }

        //查询出全部设备类型
        List<SettingsDeviceType> deviceTypeList = settingsDeviceTypeService.selectAll();
        if(deviceTypeList == null || deviceTypeList.isEmpty()){
            throw new ErrorCodeException(-1, "未查询到设备类型，请联系管理员添加");
        }
        //将设备类型list转为map，方便取值
        Map<String, String> deviceTypeMap = new HashMap<>(4);
        for(SettingsDeviceType deviceType : deviceTypeList){
            deviceTypeMap.put(deviceType.getTypename(), deviceType.getId());
        }

        for(int i=0; i<list.size(); i++){
            GbImport info = list.get(i);

            //验证国标编码 gbId
            if(!Validator.checkNumber(info.getGbId()) || info.getGbId().length() != 20){
                throw new ErrorCodeException(-1, "第"+(i+2)+"行,gbId\""+info.getGbId()+"\"填写有误");
            }

            //验证父级国标编码 parent_id
            if(!Validator.checkNumber(info.getParentGbId())){
                throw new ErrorCodeException(-1, "第"+(i+2)+"行,parent_id\""+info.getParentGbId()+"\"填写有误");
            }
            //验证节点类型 node_type
            if(info.getType() == null  || info.getType() < 0 || info.getType() > 2){
                throw new ErrorCodeException(-1, "第"+(i+2)+"行,node_type\""+info.getType()+"\"填写有误");
            }
            //查询父级ID
            String objectId =null;
            if(info.getType() ==0 ||info.getType() ==1){//机构
                SysAuthDept paramarentGbInfo = new SysAuthDept();
                paramarentGbInfo.setGbId(info.getParentGbId());
                paramarentGbInfo = sysAuthDeptService.selectByOther(paramarentGbInfo);
                objectId = paramarentGbInfo.getDeptid();
            }else if(info.getType() ==2 ) {//通道
                DeviceInfo paramarentGbInfo = new DeviceInfo();
                paramarentGbInfo.setDevice(info.getParentGbId());
                paramarentGbInfo = deviceInfoService.selectByOther(paramarentGbInfo);
                objectId = paramarentGbInfo.getId();
            }
            if(objectId == null){
                //当无法在数据库查询到父级ID的时候，去导入信息的国标中查找
                if(!gbIdSet.contains(info.getParentGbId())){
                    throw new ErrorCodeException(-1, "第"+(i+2)+"行,parent_id\""+info.getParentGbId()+"\"不存在");
                }
                if(info.getGbId().equals(info.getParentGbId())){
                    throw new ErrorCodeException(-1, "第"+(i+2)+"行,parent_id\""+info.getParentGbId()+"\"与gbId\""+info.getGbId()+"\"相同，不符合要求");
                }
                info.setParentId(gbIdMap.get(info.getParentGbId()));
            }else{
                info.setParentId(objectId);
            }



            //验证节点名称 node_name
            if(StringUtil.isEmpty(info.getName())){
                throw new ErrorCodeException(-1, "第"+(i+2)+"行,node_name\""+info.getName()+"\"为空");
            }

            //如果节点为设备 type = 1
            if(info.getType() == 1){
                //验证 IP
                if(!StringUtil.isEmpty(info.getIp()) && !Validator.checkIp(info.getIp())){
                    throw new ErrorCodeException(-1, "第"+(i+2)+"行,IP\""+info.getIp()+"\"填写有误");
                }
                //验证 port
                if(!StringUtil.isEmpty(info.getPort()) && !Validator.checkPort(info.getPort())){
                    throw new ErrorCodeException(-1, "第"+(i+2)+"行,port\""+info.getPort()+"\"填写有误");
                }
                //password 无需验证

                //验证设备类型 devicetype
                if(StringUtil.isEmpty(info.getDevicetypename())){
                    throw new ErrorCodeException(-1, "第"+(i+2)+"行,devicetype\""+info.getDevicetypename()+"\"为空");
                }else{
                    //验证设备类型是否存在
                    String devicetypeid = deviceTypeMap.get(info.getDevicetypename());
                    if(StringUtil.isEmpty(devicetypeid)){
                        throw new ErrorCodeException(-1, "第"+(i+2)+"行,devicetype\""+info.getDevicetypename()+"\"填写有误");
                    }else{
                        info.setDevicetypeid(devicetypeid);
                    }
                }
            }
        }
        return list;
    }

    @Override
    public int saveGbImport(List<GbImport> list, SysAuthUser opUser) throws Exception {
        if(list == null || list.isEmpty()){
            throw new ErrorCodeException(-1, "导入记录为空");
        }
        //循环插入国标信息
        for(GbImport info : list){
            GbImport gbInfo = info;
            //保存其它信息
            switch (info.getType()){
                case 0:
                    //保存机构
                    SysAuthDept sysAuthDept = new SysAuthDept();
                    sysAuthDept.setDeptid(gbInfo.getId());
                    sysAuthDept.setGbId(gbInfo.getGbId());
                    sysAuthDept.setParentid(gbInfo.getParentId());
                    sysAuthDept.setDeptname(gbInfo.getName());
                    sysAuthDept.setOpUserid(opUser.getUserid());
                    sysAuthDept.setCreateUser(opUser.getUsername());
                    String deptIdNew = sysAuthDeptService.getDeptIdNew(gbInfo.getParentId());
                    sysAuthDept.setDeptidnew(deptIdNew);
                    sysAuthDeptService.save(sysAuthDept);
                    break;
                case 1:
                    //保存设备
                    DeviceInfo deviceInfo = new DeviceInfo();
                    deviceInfo.setId(gbInfo.getId());
                    deviceInfo.setDevice(gbInfo.getGbId());
                    deviceInfo.setDeptid(gbInfo.getParentId());
                    deviceInfo.setDevicename(gbInfo.getName());
                    deviceInfo.setDevicetypeid(info.getDevicetypeid());
                    deviceInfo.setIp(info.getIp());
                    deviceInfo.setPort(info.getPort());
                    deviceInfo.setPassword(info.getPassword());
                    deviceInfo.setCreateUser(opUser.getUsername());
                    deviceInfoService.addDeviceInfo(deviceInfo);
                    break;
                case 2:
                    //保存通道
                    DeviceChannelInfo deviceChannelInfo = new DeviceChannelInfo();
                    deviceChannelInfo.setId(gbInfo.getId());
                    deviceChannelInfo.setChannel(gbInfo.getGbId());
                    deviceChannelInfo.setDeviceid(gbInfo.getParentId());
                    deviceChannelInfo.setChannelname(gbInfo.getName());
                    deviceChannelInfoService.save(deviceChannelInfo);
                    break;
            }
        }
        return 1;
    }
}
